﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;

namespace AudioEffectBox
{
    public class CyclingStream : Stream
    {
        public Stream BaseStream { get; set; }
        
        
        public CyclingStream(Stream _stream)
        {
            BaseStream = _stream;            
            if (!BaseStream.CanSeek) throw new ArgumentException("The stream must be seekable");
           
        }
        public override bool CanRead
        {
            get { return BaseStream.CanRead; }
        }

        public override bool CanSeek
        {
            get { return BaseStream.CanSeek; }
        }

        public override bool CanWrite
        {
            get { return BaseStream.CanWrite; }
        }

        public override void Flush()
        {
            BaseStream.Flush();
        }

        public override long Length
        {
            get { return long.MaxValue; }
        }

        public override long Position
        {
            get { return BaseStream.Position; }
            set { BaseStream.Position = value; }
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            lock (this)
            {
                int _bytesRemaining = count;
                while (_bytesRemaining != 0)
                {
                    int _totalRead = BaseStream.Read(buffer, offset, _bytesRemaining);
                    offset += _totalRead;
                    _bytesRemaining -= _totalRead;
                    if (_bytesRemaining != 0) BaseStream.Seek(0, SeekOrigin.Begin);
                }
                return count;
            }
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            return BaseStream.Seek(offset, origin);
        }

        public override void SetLength(long value)
        {
            BaseStream.SetLength(value);
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            if ((BaseStream.Position + count) > BaseStream.Length)
            {
                int delta = (int)(BaseStream.Length - BaseStream.Position);
                BaseStream.Write(buffer, offset, delta);
                BaseStream.Seek(0, SeekOrigin.Begin);
                BaseStream.Write(buffer, offset+ delta,count-delta);

            }
            else
                BaseStream.Write(buffer, offset, count);
        }
    }
}
